#ifndef LUA_UTILS_H
#define LUA_UTILS_H

#include "lua.hpp"
#include "AbstractObject.h"

AbstractObject* unboxAO(lua_State* L, int pos);
AbstractObject* typeCheckUnboxAO(lua_State* L, int pos, const std::string& tname);
AnyAOPtr unboxAOPtr(lua_State* L, int pos);
AnyAOPtr unboxAOPtrSafe(lua_State* L, int pos, const std::string& tname);

void pushIData(lua_State* L, IData& idata);
IData popIData(lua_State* L, int pos);

const char* getSafeLuaString(lua_State* L, int pos);

template <class T>
void pushNumericalArray(lua_State *L, T* arr, int arrsize)
{
	lua_newtable(L);
	for(int i = 0; i < arrsize; ++i)
	{
		lua_pushnumber(L, (lua_Number)(arr[i]));
		lua_rawseti(L, -2, i+1);
	}
	return;
}

template <class T>
T* pop_custom(lua_State *L, int p, const char* name)
{
	void* ud = luaL_checkudata(L, p, name);
	luaL_argcheck(L, ud != NULL, 1, "Type error!");
	T** temp = (T**)ud;
	return *temp;
}

template <class T>
void push_custom(lua_State* L, T* val, const char* name)
{
	T** a = (T**)lua_newuserdata(L, sizeof(T*));
	*a = new T(*val);

	luaL_getmetatable(L, name);
	lua_setmetatable(L, -2);
}

template <class T>
void push_custom_nocopy(lua_State* L, T* val, const char* name)
{
	T** a = (T**)lua_newuserdata(L, sizeof(T*));
	*a = val;

	luaL_getmetatable(L, name);
	lua_setmetatable(L, -2);
}


#endif
